package com.gujiangbo.application.common.trace;

import java.util.StringTokenizer;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;

import com.gujiangbo.application.common.trace.context.TraceContext;
import com.gujiangbo.application.common.trace.context.TraceContextHolder;
import com.gujiangbo.application.common.trace.event.TraceEvent;
import com.gujiangbo.application.common.trace.utils.TraceUtils;

public class TraceManager {

	private static final String DEFAULT_SPLIT = ".";
	private static final String SEQNO_DEFAULT = "1";

	public static String genNewTraceID() {
		return UUID.randomUUID().toString().replace("-", "");
	}

	public static void setTraceID(String traceID) {
		setTraceID(traceID, TraceContextHolder.getDataContext());
	}

	public static void setTraceID(String traceID, TraceContext traceContext) {
		traceContext.setTraceID(traceID);
	}

	public static String getTraceID() {
		return getTraceID(TraceContextHolder.getDataContext());
	}

	public static String getTraceID(TraceContext traceContext) {
		return traceContext.getTraceID();
	}

	public static String genNextSeqNo(String seqNo) {
		StringBuilder sbNextSeqNo = new StringBuilder(seqNo);
		sbNextSeqNo.append(".").append("1");

		return sbNextSeqNo.toString();
	}

	public static String getAndIncrementSeqNo(String seqNo) {
		StringTokenizer seqNoToken = new StringTokenizer(seqNo, ".");

		int count = seqNoToken.countTokens();
		int index = 0;
		StringBuilder newSeqNo = new StringBuilder();
		while (seqNoToken.hasMoreTokens()) {
			if (index < count - 1) {
				newSeqNo.append(seqNoToken.nextToken()).append(".");
				index++;
			} else {
				int leafNo = new Integer(seqNoToken.nextToken()).intValue() + 1;
				newSeqNo.append(leafNo);
			}
		}
		return newSeqNo.toString();
	}

	public static void setSeqNo(String seqNo) {
		setSeqNo(seqNo, TraceContextHolder.getDataContext());
	}

	public static void setSeqNo(String seqNo, TraceContext traceContext) {
		traceContext.setContext("seqNo", seqNo);
	}

	public static String getSeqNo() {
		return getSeqNo(TraceContextHolder.getDataContext());
	}

	public static String getSeqNo(TraceContext traceContext) {
		return (String) traceContext.getContext("seqNo");
	}

	public static void setExtendInfo(String extendInfo) {
		setExtendInfo(extendInfo, TraceContextHolder.getDataContext());
	}

	public static void setExtendInfo(String extendInfo, TraceContext traceContext) {
		traceContext.setContext("extendInfo", extendInfo);
	}

	public static String getExtendInfo() {
		return getExtendInfo(TraceContextHolder.getDataContext());
	}

	public static String getExtendInfo(TraceContext traceContext) {
		return (String) traceContext.getContext("extendInfo");
	}

	public static void setTraceFlag(int traceflag) {
		setTraceFlag(traceflag, TraceContextHolder.getDataContext());
	}

	public static void setTraceFlag(int traceflag, TraceContext traceContext) {
		traceContext.setTraceFlag(traceflag);
	}

	public static int getTraceFlag() {
		return getTraceFlag(TraceContextHolder.getDataContext());
	}

	public static int getTraceFlag(TraceContext traceContext) {
		return traceContext.getTraceFlag();
	}

	public static void setCallNumber(int callnumber) {
		setCallNumber(callnumber, TraceContextHolder.getDataContext());
	}

	public static void setCallNumber(int callnumber, TraceContext traceContext) {
		traceContext.setCallNumber(callnumber);
	}

	public static int getCallNumber() {
		return getCallNumber(TraceContextHolder.getDataContext());
	}

	public static int getCallNumber(TraceContext traceContext) {
		return traceContext.getCallNumber();
	}

	public static void setPlatFormExtendInfo(String platformextendInfo) {
		setPlatFormExtendInfo(platformextendInfo, TraceContextHolder.getDataContext());
	}

	public static void setPlatFormExtendInfo(String platformextendInfo, TraceContext traceContext) {
		traceContext.setContext("PlatformExtendInfo", platformextendInfo);
	}

	public static String getPlatFormExtendInfo() {
		return getPlatFormExtendInfo(TraceContextHolder.getDataContext());
	}

	public static String getPlatFormExtendInfo(TraceContext traceContext) {
		return (String) traceContext.getContext("PlatformExtendInfo");
	}

	public static void setCodeStream(String codestream) {
		setCodeStream(codestream, TraceContextHolder.getDataContext());
	}

	public static void setCodeStream(String codestream, TraceContext dc) {
		dc.setContext("CodeStream", codestream);
	}

	public static String getCodeStream() {
		return getCodeStream(TraceContextHolder.getDataContext());
	}

	public static String getCodeStream(TraceContext dc) {
		return (String) dc.getContext("CodeStream");
	}

	public static void sethasComparedTrace(boolean comparedflag) {
		sethasComparedTrace(comparedflag, TraceContextHolder.getDataContext());
	}

	public static void sethasComparedTrace(boolean comparedflag, TraceContext dc) {
		dc.sethasComparedTrace(comparedflag);
	}

	public static boolean gethasComparedTrace() {
		return gethasComparedTrace(TraceContextHolder.getDataContext());
	}

	public static boolean gethasComparedTrace(TraceContext dc) {
		return dc.gethasComparedTrace();
	}

	public static boolean check(ITraceLinkMessage traceMsg) {
		if (StringUtils.isEmpty(traceMsg.getTraceID())) {
			return false;
		}
		if (StringUtils.isEmpty(traceMsg.getSeqNo())) {
			return false;
		}
		if (StringUtils.isEmpty(traceMsg.getProperty("calledNodeID"))) {
			return false;
		}
		if (StringUtils.isEmpty(traceMsg.getProperty("calledClusterId"))) {
			return false;
		}
		if (StringUtils.isEmpty(traceMsg.getProperty("flag"))) {
			return false;
		}
		if (StringUtils.isEmpty(traceMsg.getProperty("appName"))) {
			return false;
		}
		if (StringUtils.isEmpty(traceMsg.getProperty("subSysName"))) {
			return false;
		}
		if (StringUtils.isEmpty(traceMsg.getProperty("protocol"))) {
			return false;
		}
		return true;
	}

	public static String format(ITraceLinkMessage traceMsg) {
		String convertPattern = traceMsg.getConverPattern();
		if (StringUtils.isEmpty(convertPattern)) {
			convertPattern = "traceID|calledNodeID|calledClusterId|calledIP|callingNodeID|callingIP|Flag|appName|subSysName|protocol|beginTime|endTime|reqMsgSize|rspMsgSize|resultCode|resultInfo|seqNo|extendInfo";
		}
		StringTokenizer st = new StringTokenizer(convertPattern, "|");
		StringBuilder formalMessage = new StringBuilder("");
		int count = st.countTokens();
		int i = 0;
		while (st.hasMoreTokens()) {
			String key = st.nextToken();
			String value = traceMsg.getProperty(key);
			formalMessage.append(value == null ? "" : value);
			if (i < count - 1) {
				formalMessage.append("|");
			}
			i++;
		}
		return formalMessage.toString();
	}

	public static String format(TraceEvent traceEvent, String convertPattern) {
		if (StringUtils.isEmpty(convertPattern)) {
			convertPattern = "traceID|calledNodeID|calledClusterId|calledIP|callingNodeID|callingIP|Flag|appName|subSysName|protocol|beginTime|endTime|reqMsgSize|rspMsgSize|resultCode|resultInfo|seqNo|extendInfo";
		}
		StringTokenizer st = new StringTokenizer(convertPattern, "|");
		StringBuilder formalMessage = new StringBuilder("");
		int count = st.countTokens();
		int i = 0;
		while (st.hasMoreTokens()) {
			String key = st.nextToken();
			String value = traceEvent.getProperty(key);
			formalMessage.append(value == null ? "" : value);
			if (i < count - 1) {
				formalMessage.append("|");
			}
			i++;
		}
		return formalMessage.toString();
	}

	public static boolean save(ITraceLinkMessage traceMsg) {
		long endTimeLong = System.currentTimeMillis();

		traceMsg.setProperty("endTime", TraceUtils.convertDate2MSString(endTimeLong));
		traceMsg.trace();
		return true;
	}

	public static void removeAttribute(String key, TraceContext dc) {
		dc.removeAttribute(key);
	}

	public static void clear() {
		TraceContext traceContext = TraceContextHolder.getDataContext();
		clear(traceContext);
	}

	public static void clear(TraceContext traceContext) {
		traceContext.clearTraceLinkInfo();

		traceContext.removeAttribute("seqNo");
	}

	public static void setAppName(String appName, TraceContext dc) {
		dc.setAppName(appName);
	}

	public static String getAppName(TraceContext dc) {
		return dc.getAppName();
	}

	public static void setServerHeader(String serverheader) {
		TraceContextHolder.getDataContext().setServerHeader(serverheader);
	}

	public static String getServerHeader() {
		return TraceContextHolder.getDataContext().getServerHeader();
	}

}
